﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataTransferObject;
using DataTransferObject.MapUnMapTime;


namespace Engine.TaskVerification
{
    /// <summary>
    /// used for pragmatic algo to verify task constraint before prioritize or scheduling
    /// </summary>
    class PragmaticVerifyTaskConstraintAlgo : IVerifyTasksConstraint
    {
        public bool doTaskVerification(TaskList taskList, MappedFreeTimeList mappedFreeTimeList, 
            SystemConfiguration systemConfiguration, ref ConstraintViolation constraintViolation)
        {
            Double workHours = 0;
            int countWorkingHour = systemConfiguration.TabWorkingHoursData.ListOfWorkingHourItems.Count;
            int countTasks = taskList.GetTaskList.Count;

            //mang chua remainTime cua tat ca cac tasks co cung workingHour, index ung voi workingHour
            double[] totalTasksWorks = new double[countWorkingHour];
            //mang chua total Time cua tung working Hour
            double[] totalTimeWH = new double[countWorkingHour];
            //mang chua cac workingHourList
            List<MappedFreeTimeList> workingHourList = new List<MappedFreeTimeList>();
            MappedFreeTimeList unionedList = new MappedFreeTimeList();
            MappedFreeTimeList scaledWorkingHourList = new MappedFreeTimeList(); //list cac working Hour da duoc enlarge
            MappedFreeTimeList mergedWHList = new MappedFreeTimeList(); //merged workingHour List
            MappedFreeTimeList globalList = mappedFreeTimeList; //free Time List

            
            //Initial the totalTasksWorks list
            for(int i = 0; i < countWorkingHour; i++)
            {
                totalTasksWorks[i] = 0;
            }

            //Initial the totalTimeWH list
            for (int i = 0; i < countWorkingHour; i++)
            {
                totalTimeWH[i] = 0;
            }

            //Calculate remainTime for each group of Tasks correspond to wokingHours
            for (int i = 0; i < countTasks; i++)
            {
                int indexWorkingHour = taskList.GetTaskList[i].WorkingHourID;
                workHours = taskList.GetTaskList[i].RemainTime;
                totalTasksWorks[indexWorkingHour] = totalTasksWorks[indexWorkingHour] + workHours;
            }

            //map the workingHours to the Time axis base on the offset of global freetimelist
            for (int i = 0; i < countWorkingHour; i++)
            {
                workingHourList.Add(systemConfiguration.TabWorkingHoursData.ListOfWorkingHourItems[i].WorkTime);
            }
            mergedWHList = MappingService.mergeWorkingHourList_1week(workingHourList);

            for (int i = 0; i < countWorkingHour; i++)
            {
                scaledWorkingHourList = MappingService.enlargeWorkingHourListToFTListSize(mergedWHList, globalList.ListFreeTimeBlock.Last().End);
            }
            
            //intersect every workingHour with global list
            for (int i = 0; i < countWorkingHour; i++)
            {
                workingHourList[i] = MappingService.intersectFreeTimeList(workingHourList[i], mappedFreeTimeList);
            }
            
            //calculate total time cua tung workingHour
            //dong thoi
            //kiem tra xem total time cua tung group cac tasks co nho hon total time cua tung workingHour tuong ung
            for (int i = 0; i < countWorkingHour; i++)
            {
                for (int j = 0; j < workingHourList[i].ListFreeTimeBlock.Count; j++)
                {
                    totalTimeWH[i] = totalTimeWH[i] + workingHourList[i].ListFreeTimeBlock[j].End - workingHourList[i].ListFreeTimeBlock[j].Start;
                }
                if (totalTasksWorks[i] > totalTimeWH[i])
                    return false;
            }

            //Union cac working Hour
            unionedList = MappingService.unionMultipleFreeTimeList(workingHourList);
            
            //total check
            double sum = 0;
            for (int i = 0; i < countWorkingHour; i++)
            {
                sum = sum + totalTasksWorks[i];
            }

            for (int i = 0; i < unionedList.ListFreeTimeBlock.Count; i++)
            {
                sum = sum - (unionedList.ListFreeTimeBlock[i].End - unionedList.ListFreeTimeBlock[i].Start);
            }

            if (sum > 0)
                return false;

            return true;
        }




        public bool doTaskVerification(TaskList taskList, FreeTimeList freeTimeList, ref ConstraintViolation constraintViolation)
        {
            throw new NotImplementedException();
        }
    }
}
